#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <libwebsockets.h>

#define KGRN "\033[0;32;32m"
#define KCYN "\033[0;36m"
#define KRED "\033[0;32;31m"
#define KYEL "\033[1;33m"
#define KBLU "\033[0;32;34m"
#define KCYN_L "\033[1;36m"
#define KBRN "\033[0;33m"
#define RESET "\033[0m"

static int destroy_flag = 0;
static int connection_flag = 0;
static int writeable_flag = 0;


#include "janus.h"
#include "cmdline.h"
#include "config.h"
#include "apierror.h"
#include "log.h"
#include "debug.h"
#include "rtcp.h"
#include "auth.h"
#include "utils.h"

#include "./transports/transport.h"
static size_t json_format = JSON_INDENT(3) | JSON_PRESERVE_ORDER;
int janus_process_incoming_request(janus_request *request) ;


/* Transport plugin information */
#define JANUS_PEAR_VERSION			1
#define JANUS_PEAR_VERSION_STRING	"0.0.1"
#define JANUS_PEAR_DESCRIPTION		"Pear.hk"
#define JANUS_PEAR_NAME				"Pear.hk"
#define JANUS_PEAR_AUTHOR				"Yongmig.li"
#define JANUS_PEAR_PACKAGE			"janus.transport.Pear"

 
/*! \brief pear session */

Pear_session pear_session;

#define PEAR_StateInit  0
#define PEAR_StateCreate 1
#define PEAR_StateAttach  2
#define PEAR_StateMessage  3
#define PEAR_StateSDP  4

extern GThreadPool *tasks ;

static int myindex =0;
char * pear_msg [] = {"{\"open\":true,\"channel\":\"janus\"}",
	                  "{\"data\":{\"userid\":\"janus\",\"broadcasting\":true},\"channel\":\"janus\"}",
	                  //"{\"data\":{\"participationRequest\":true,\"userid\":\"janus\",\"to\":\"A\"},\"channel\":\"janus\"}",
	                  pear_session.req,
	                  pear_session.candidate_signal,
	                   "{\"data\":{\"isCreateDataChannel\":true,\"userid\":\"janus\",\"to\":\"A\"},\"channel\":\"janus\"}"
                       };

char * pear_msg_simple [] = {
	                    "{\"open\":true,\"channel\":\"janus\"}",
	                    pear_session.req
                       };


#ifdef PEAR

http://stackoverflow.com/questions/30904560/libwebsocket-client-example

// js datachannel transfer file 
{"open":true,"channel":"113.28.150.72"}
{"data":{"userid":"A","broadcasting":true},"channel":"113.28.150.72"}
{"data":{"userid":"B","broadcasting":true},"channel":"113.28.150.72"}
{"data":{"participationRequest":true,"userid":"A","to":"B"},"channel":"113.28.150.72"}
{"data":{"userid":"A","broadcasting":true},"channel":"113.28.150.72"}
{"data":{"participationRequest":true,"userid":"B","to":"A"},"channel":"113.28.150.72"}
{"data":{"userid":"B","broadcasting":true},"channel":"113.28.150.72"}
{"data":{"userid":"B","sdp":{"type":"offer","sdp":"v=0\r\no=- 2346679318976397011 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=msid-semantic: WMS\r\nm=application 35173 DTLS/SCTP 5000\r\nc=IN IP4 183.39.156.136\r\na=candidate:297624883 1 udp 2113937151 192.168.31.165 35173 typ host generation 0 network-cost 50\r\na=candidate:842163049 1 udp 1677729535 183.39.156.136 35173 typ srflx raddr 192.168.31.165 rport 35173 generation 0 network-cost 50\r\na=ice-ufrag:yAOo\r\na=ice-pwd:UOZgBLckvfy3ZJjD90l8DooO\r\na=fingerprint:sha-256 7A:AC:2D:FA:8A:75:34:C0:0F:EB:B9:1D:80:01:42:35:36:AB:FA:56:E5:FD:8D:80:E2:7C:A8:27:58:30:F5:86\r\na=setup:actpass\r\na=mid:data\r\na=sctpmap:5000 webrtc-datachannel 1024\r\n"},"to":"A"},"channel":"113.28.150.72"}
{"data":{"userid":"A","sdp":{"type":"answer","sdp":"v=0\r\no=- 5632509814238704138 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=msid-semantic: WMS\r\nm=application 9 DTLS/SCTP 5000\r\nc=IN IP4 0.0.0.0\r\nb=AS:30\r\na=ice-ufrag:mrgQ\r\na=ice-pwd:ZKX1+61LM/ApXH99gFsqqRai\r\na=fingerprint:sha-256 5E:B9:61:81:D2:9F:63:71:25:32:E8:D6:75:95:06:B6:B8:3C:8D:F0:BC:3C:82:C8:D0:B3:05:00:07:AC:1F:84\r\na=setup:active\r\na=mid:data\r\na=sctpmap:5000 webrtc-datachannel 1024\r\n"},"to":"B"},"channel":"113.28.150.72"}
{"data":{"userid":"A","candidate":{"candidate":"candidate:297624883 1 udp 2113937151 192.168.31.165 36430 typ host generation 0 ufrag mrgQ network-cost 50","sdpMid":"data","sdpMLineIndex":0},"to":"B"},"channel":"113.28.150.72"}
{"data":{"userid":"A","sdp":{"type":"offer","sdp":"v=0\r\no=- 1318540410322674005 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=msid-semantic: WMS\r\nm=application 60226 DTLS/SCTP 5000\r\nc=IN IP4 183.39.156.136\r\na=candidate:297624883 1 udp 2113937151 192.168.31.165 60226 typ host generation 0 network-cost 50\r\na=candidate:842163049 1 udp 1677729535 183.39.156.136 60226 typ srflx raddr 192.168.31.165 rport 60226 generation 0 network-cost 50\r\na=ice-ufrag:Qe0J\r\na=ice-pwd:j+ZHCpRjxxT5Nw6vprS4iExS\r\na=fingerprint:sha-256 6D:2F:DC:F2:87:AF:87:A4:8B:80:B4:F1:04:FC:BE:28:60:E3:D5:04:92:D6:FB:20:80:D8:F1:9F:A6:DA:A9:CC\r\na=setup:actpass\r\na=mid:data\r\na=sctpmap:5000 webrtc-datachannel 1024\r\n"},"to":"B"},"channel":"113.28.150.72"}
{"data":{"userid":"B","sdp":{"type":"answer","sdp":"v=0\r\no=- 3401124500555772435 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=msid-semantic: WMS\r\nm=application 9 DTLS/SCTP 5000\r\nc=IN IP4 0.0.0.0\r\nb=AS:30\r\na=ice-ufrag:gLKC\r\na=ice-pwd:9YlqQ3ouPIFF2ZM/aaOWRXQv\r\na=fingerprint:sha-256 06:24:A3:C4:B8:0B:8B:56:45:62:D2:8F:DE:A8:B0:BD:64:54:58:B5:E6:12:E4:F4:F0:BB:CA:F9:71:49:91:87\r\na=setup:active\r\na=mid:data\r\na=sctpmap:5000 webrtc-datachannel 1024\r\n"},"to":"A"},"channel":"113.28.150.72"}
{"data":{"userid":"B","candidate":{"candidate":"candidate:297624883 1 udp 2113937151 192.168.31.165 54560 typ host generation 0 ufrag gLKC network-cost 50","sdpMid":"data","sdpMLineIndex":0},"to":"A"},"channel":"113.28.150.72"}
{"data":{"userid":"A","broadcasting":true},"channel":"113.28.150.72"}

//  janus
//  {"janus":"create","transaction":"YiWjUZa8nu84"}
//  {"janus":"attach","plugin":"janus.plugin.textroom","transaction":"AOytkinnTwJP","session_id":1677657978734222}
//  {"janus":"message","body":{"request":"setup"},"transaction":"Zx2JOhwFy19N","session_id":1677657978734222,"handle_id":3533919513060053}
//  There's a message for JANUS TextRoom plugin

<---------------------------------------------------------------------
{"janus":"create","transaction":"o53t2NLXPMVb"}
--------------------------------------------------------------------->
{
   "janus": "success",
   "transaction": "KElHTiisVZAB",
   "data": {
      "id": 5840022919692368
   }
}

<---------------------------------------------------------------------
{"janus":"attach","plugin":"janus.plugin.textroom","transaction":"eqjcjpCKVsBc","session_id":5840022919692368}
---------------------------------------------------------------------->
{
   "janus": "success",
   "session_id": 5840022919692368,
   "transaction": "eqjcjpCKVsBc",
   "data": {
      "id": 2262232448363641
   }
}
<---------------------------------------------------------------------
{"janus":"message","body":{"request":"setup"},"transaction":"icaQQcvLxxDn","session_id":5840022919692368,"handle_id":2262232448363641}
---------------------------------------------------------------------->
{
   "janus": "ack",
   "session_id": 5840022919692368,
   "hint": "I'm taking my time!",
   "transaction": "icaQQcvLxxDn"
}

---------------------------------------------------------------------->
{
   "janus": "event",
   "session_id": 5840022919692368,
   "sender": 2262232448363641,
   "transaction": "icaQQcvLxxDn",
   "plugindata": {
      "plugin": "janus.plugin.textroom",
      "data": {
         "textroom": "event",
         "result": "ok"
      }
   },
   "jsep": {
      "type": "offer",
      "sdp": "v=0\r\no=- 1482845804297219 1482845804297219 IN IP4 192.168.31.165\r\ns=Janus TextRoom plugin\r\nt=0 0\r\na=group:BUNDLE data\r\na=msid-semantic: WMS janus\r\nm=application 9 DTLS/SCTP 5000\r\nc=IN IP4 192.168.31.165\r\na=sendrecv\r\na=sctpmap:5000 webrtc-datachannel 16\r\na=mid:data\r\na=ice-ufrag:FEr0\r\na=ice-pwd:BuTGGup+0EkQ4fAhIKpkc4\r\na=ice-options:trickle\r\na=fingerprint:sha-256 D2:B9:31:8F:DF:24:D8:0E:ED:D2:EF:25:9E:AF:6F:B8:34:AE:53:9C:E6:F3:8F:F2:64:15:FA:E8:7F:53:2D:38\r\na=setup:actpass\r\na=candidate:1 1 udp 2013266431 192.168.31.165 34175 typ host\r\n"
   }
}

<------------------------------------------------------------------------------
{"janus":"message","body":{"request":"ack"},"transaction":"FUWWe3M11TKd","jsep":{"type":"answer","sdp":"v=0\r\no=- 3988597792883216556 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=msid-semantic: WMS\r\nm=application 9 DTLS/SCTP 5000\r\nc=IN IP4 0.0.0.0\r\nb=AS:30\r\na=ice-ufrag:s1FM\r\na=ice-pwd:Hwqg+BLL24CmBYzuZhQApxoO\r\na=fingerprint:sha-256 ED:0D:3B:9A:01:2D:03:F4:16:D4:F5:F5:9B:EF:A6:DC:51:6D:E3:34:22:B9:05:5E:8E:01:44:DB:D3:7F:34:16\r\na=setup:active\r\na=mid:data\r\na=sctpmap:5000 webrtc-datachannel 1024\r\n"},"session_id":5840022919692368,"handle_id":2262232448363641}

{"janus":"trickle","candidate":{"candidate":"candidate:297624883 1 udp 2113937151 192.168.31.165 38847 typ host generation 0 ufrag s1FM network-cost 50","sdpMid":"data","sdpMLineIndex":0},"transaction":"Qn6UqjRYkOuZ","session_id":5840022919692368,"handle_id":2262232448363641}

<------------------------------------------------------------------------------
{"janus":"trickle","candidate":{"completed":true},"transaction":"Tk9ug2rnpEhI","session_id":5840022919692368,"handle_id":2262232448363641}



	json_t *root = request->message;
	json_t *transaction = json_object_get(root, "transaction");
	const gchar *transaction_text = json_string_value(transaction);
	json_t *message = json_object_get(root, "janus");
	const gchar *message_text = json_string_value(message);

{"janus":"attach","plugin":"janus.plugin.textroom","transaction":"tGNeEvHiqfIT","session_id":3744281348133001}

#endif 

static void INT_HANDLER(int signo) {
    destroy_flag = 1;
}

struct session_data {
    int fd;
};

struct pthread_routine_tool {
    struct lws_context *context;
    struct lws *wsi;
};

static int websocket_write_back(struct lws *wsi_in, char *str, int str_size_in) 
{
    if (str == NULL || wsi_in == NULL)
        return -1;

    int n;
    int len;
    char *out = NULL;

    if (str_size_in < 1) 
        len = strlen(str);
    else
        len = str_size_in;

    out = (char *)malloc(sizeof(char)*(LWS_SEND_BUFFER_PRE_PADDING + len + LWS_SEND_BUFFER_POST_PADDING));
    //* setup the buffer*/
    memcpy (out + LWS_SEND_BUFFER_PRE_PADDING, str, len );
    //* write out*/
    n = lws_write(wsi_in, out + LWS_SEND_BUFFER_PRE_PADDING, len, LWS_WRITE_TEXT);

    //printf(KBLU"[websocket_write_back] -------------->>> %s\n"RESET, str);
    //* free the buffer*/
    free(out);

    return n;
}

void pear_send_signal()
{
       char * str = "{\"data\":{\"isCreateDataChannel\":true,\"userid\":\"janus\",\"to\":\"A\"},\"channel\":\"janus\"}";
}


void pear_parse_signal_simple(char * data)
{

      //{"type":"answer","sdp":"\r\n"}

       json_error_t error;
	json_t * root = NULL;
	
	json_t * candidate = NULL;
	json_t * sdp=   NULL;
	json_t * type=   NULL;
	char * type_str;
	char * sdp_str;
	char * candidate_str;

	 root = json_loads(data, 0, &error);
        sdp  = json_object_get(root, "sdp");
	 type = json_object_get(root, "type");

	if(sdp && type)
	{
	         type_str = json_string_value(type);
	         sdp_str = json_string_value(sdp);
		  JANUS_LOG(LOG_INFO,KCYN_L"parse type is  %s and sdp is :%s\n"RESET, type_str,sdp_str);
		  strcpy(pear_session.answer,sdp_str);
		  //janus_string_replace((char *)pear_session.answer,"active", "actpass" );
		  pear_send_answer_message();
	}
	//{"candidate":" ","sdpMid":"data","sdpMLineIndex":0}

      candidate=json_object_get(root, "candidate");
      if(candidate)
      {
           candidate_str = json_string_value(candidate);
	    JANUS_LOG(LOG_INFO,KCYN_L"parse candidate is  %s \n"RESET, candidate_str);
	    strcpy(pear_session.candidate,candidate_str);
	    pear_send_candidate_message();
	    pear_send_candidate_completed_message();

      }
	

}
void pear_parse_signal(char * data)
{

    //  {"userid":"A","sdp":{"type":"answer","sdp":""},"to":"janus"}

       json_error_t error;
	json_t * root = NULL;
	json_t * candidate = NULL;
	json_t * candidate_detail = NULL;
	char * candidate_str;
	
	json_t * sdp=   NULL;
	json_t * sdp_detail=   NULL;
	json_t * type=   NULL;
	char * type_str;
	char * sdp_str;

	 root = json_loads(data, 0, &error);
        sdp  = json_object_get(root, "sdp");
	 type = json_object_get(sdp, "type");
	 sdp_detail = json_object_get(sdp, "sdp");
	if(sdp)
	{
	    if(type)
	    {
	         type_str = json_string_value(type);
	         sdp_str = json_string_value(sdp_detail);
		  JANUS_LOG(LOG_INFO,KCYN_L"parse type is  %s and sdp is :%s\n"RESET, type_str,sdp_str);
		  strcpy(pear_session.answer,sdp_str);
		  pear_send_answer_message();
		  
	    }
	}
	//{"userid":"A","candidate":{"candidate":"candidate:192.168.31.165 42224","sdpMid":"data","sdpMLineIndex":0},"to":"janus"}

      candidate=json_object_get(root, "candidate");
      candidate_detail =json_object_get(candidate, "candidate");
      if(candidate)
      {
           candidate_str = json_string_value(candidate_detail);
	    JANUS_LOG(LOG_INFO,KCYN_L"parse candidate is  %s \n"RESET, candidate_str);
	    strcpy(pear_session.candidate,candidate_str);
	    pear_send_candidate_message();
	    pear_send_candidate_completed_message();

      }


	

}
static int ws_service_callback(
                         struct lws *wsi,
                         enum lws_callback_reasons reason, void *user,
                         void *in, size_t len)
{

    switch (reason) {

        case LWS_CALLBACK_CLIENT_ESTABLISHED:
            printf(KYEL"[Main Service] Connect with server success.\n"RESET);
            connection_flag = 1;
            break;

        case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
            printf(KRED"[Main Service] Connect with server error.\n"RESET);
            destroy_flag = 1;
            connection_flag = 0;
            break;

        case LWS_CALLBACK_CLOSED:
            printf(KYEL"[Main Service] LWS_CALLBACK_CLOSED\n"RESET);
            destroy_flag = 1;
            connection_flag = 0;
            break;

        case LWS_CALLBACK_CLIENT_RECEIVE:
            JANUS_LOG(LOG_INFO,KCYN_L" <<<----------------- recvived:%s\n"RESET, (char *)in);
            //pear_parse_signal((char *)in);
	     pear_parse_signal_simple((char *)in);
            //if (writeable_flag)
            //    destroy_flag = 1;

            break;
        case LWS_CALLBACK_CLIENT_WRITEABLE :
            printf(KYEL"[Main Service] On writeable is called. send byebye message\n"RESET);
	     // comment by yongmng.li for ws client test with signal server
	     if(myindex<2)
	     {
	           //websocket_write_back(wsi, pear_msg[myindex], -1);
	           //JANUS_LOG(LOG_INFO,KCYN_L"[pear]  -------------->>>  :%s\n"RESET, pear_msg[myindex]);

		    websocket_write_back(wsi, pear_msg_simple[myindex], -1);
	           JANUS_LOG(LOG_INFO,KCYN_L"[pear]  -------------->>>  :%s\n"RESET, pear_msg_simple[myindex]);
	           myindex++;
	     }

            //writeable_flag = 1;
            break;

        default:
            break;
    }

    return 0;
}

static void *pthread_routine(void *tool_in)
{
    struct pthread_routine_tool *tool = tool_in;

    printf(KBRN"[pthread_routine] Good day. This is pthread_routine.\n"RESET);

    //* waiting for connection with server done.*/
    while(!connection_flag)
        usleep(1000*20);
    //while(1)
    {

	    //*Send greeting to server*/
	    printf(KBRN"[pthread_routine] Server is ready. send a greeting message to server.\n"RESET); 

	    //websocket_write_back(tool->wsi, pear_msg[myindex++], -1);

	    printf(KBRN"[pthread_routine] sleep 2 seconds then call onWritable\n"RESET);
	    sleep(2);

	    //*involked wriable*/
	    printf(KBRN"[pthread_routine] call on writable.\n"RESET);   
	    lws_callback_on_writable(tool->wsi);
    }
}
struct pthread_routine_tool tool;
int pear_init_signal(void)
{
    //* register the signal SIGINT handler */
    struct sigaction act;
    act.sa_handler = INT_HANDLER;
    act.sa_flags = 0;
    sigemptyset(&act.sa_mask);
    sigaction( SIGINT, &act, 0);


    struct lws_context *context = NULL;
    struct lws_context_creation_info info;
    struct lws *wsi = NULL;
    struct lws_protocols protocol;

    memset(&info, 0, sizeof info);
    info.port = CONTEXT_PORT_NO_LISTEN;
    info.iface = NULL;
    info.protocols = &protocol;
    info.ssl_cert_filepath = NULL;
    info.ssl_private_key_filepath = NULL;
    info.extensions = lws_get_internal_extensions();
    info.gid = -1;
    info.uid = -1;
    info.options = 0;

    protocol.name  = "http";
    protocol.callback = &ws_service_callback;
    protocol.per_session_data_size = sizeof(struct session_data);
    protocol.rx_buffer_size = 0;
    protocol.id = 0;
    protocol.user = NULL;

    context = lws_create_context(&info);
    printf(KRED"[Main] context created.\n"RESET);

    if (context == NULL) {
        printf(KRED"[Main] context is NULL.\n"RESET);
        return -1;
    }


    wsi = lws_client_connect(context, "localhost", 12034, 0,
           "/", "localhost:12034", NULL,
             protocol.name, -1);

    //wsi = lws_client_connect(context, "119.28.2.207", 12034, 0,
   //    "/", "119.28.2.207:12034", NULL,
   //     protocol.name, -1);

    if (wsi == NULL) {
        printf(KRED"[Main] wsi create error.\n"RESET);
        return -1;
    }

    printf(KGRN"[Main] wsi create success.\n"RESET);

    
    tool.wsi = wsi;
    tool.context = context;

    pthread_t pid;
    pthread_create(&pid, NULL, pthread_routine, &tool);
    pthread_detach(pid);

    while(!destroy_flag)
    {
        lws_service(context, 50);
    }

    lws_context_destroy(context);

    return 0;
}

#if 1


void pear_session_created(void *transport, guint64 session_id) {
	/* We don't care */
}

int pear_get_api_compatibility(void) {
	/* Important! This is what your plugin MUST always return: don't lie here or bad things will happen */
	return JANUS_TRANSPORT_API_VERSION;
}

int pear_get_version(void) { 
	return JANUS_PEAR_VERSION;
}

const char *pear_get_version_string(void) {
	return JANUS_PEAR_VERSION_STRING;
}

const char *pear_get_description(void) {
	return JANUS_PEAR_DESCRIPTION;
}

const char *pear_get_name(void) {
	return JANUS_PEAR_NAME;
}

const char *pear_get_author(void) {
	return JANUS_PEAR_AUTHOR;
}

const char *pear_get_package(void) {
	return JANUS_PEAR_PACKAGE;
}

gboolean pear_is_janus_api_enabled(void) {
	return FALSE;
}

gboolean pear_is_admin_api_enabled(void) {
	return FALSE;
}

int janus_pear_init(janus_transport_callbacks *callback, const char *config_path) {
     return 0;
}
void janus_pear_destroy(void) {
    return;
}

void pear_dump_session()
{
    JANUS_LOG(LOG_INFO, "[pear] session_id :  %"SCNu64"...\n", pear_session.session_id);
    JANUS_LOG(LOG_INFO, "[pear] handle_id :  %"SCNu64"...\n", pear_session.handle_id);
   JANUS_LOG(LOG_INFO, "[pear]  sdp : %s...\n", pear_session.sdp);
}

void pear_send_sdp_signal()
{
    // {"data":{"userid":"B","sdp":{"type":"offer","sdp":""},"to":"A"},"channel":"113.28.150.72"}
    
    json_t * req = json_object();
    json_object_set_new(req, "channel", json_string("janus"));
    json_t * data = json_object();
    json_object_set_new(data, "userid", json_string("janus"));
    json_object_set_new(data, "to", json_string("A"));

    json_t * sdp = json_object();
    json_object_set_new(sdp, "type", json_string("offer"));
    json_object_set_new(sdp, "sdp", json_string(pear_session.sdp));
    json_object_set_new(data, "sdp", sdp);

     json_object_set_new(req, "data", data);

     char *payload = json_dumps(req, json_format);
    JANUS_LOG(LOG_DBG, "[pear] send sdp is %s \n",payload);
    strcpy(pear_session.req,payload);
    //websocket_write_back(tool->wsi, payload , -1);

     
}

void pear_send_sdp_signal_sample()
{

    char *value = g_strdup(pear_session.sdp);
    JANUS_LOG(LOG_DBG, "[pear] send sdp is %s \n",value);
    //value = janus_string_replace((char *)value, "a=ice-options:trickle\r\n","" );

    json_t * req = json_object();
     json_t * data = json_object();
    json_object_set_new(data, "type", json_string("offer"));
    json_object_set_new(data, "sdp", json_string(value));
    json_object_set_new(req, "data", data);
    json_object_set_new(req, "channel", json_string("janus"));

     

     char *payload = json_dumps(req, json_format);
    JANUS_LOG(LOG_DBG, "[pear] send sdp is %s \n",payload);

     strcpy(pear_session.req,payload);

}
int janus_pear_send_message(void *transport, void *request_id, gboolean admin, json_t *message) {

	char *payload = json_dumps(message, json_format);
	//  added by yongming.li 
	JANUS_LOG(LOG_DBG, "[pear] send msg is %s and state is %d\n",payload,pear_session.state);
	json_t *data=NULL;
	
	if( pear_session.state == PEAR_StateCreate)
	{
	        data = json_object_get(message, "data");
		 json_t * id = json_object_get(data, "id");
		 pear_session.session_id=json_integer_value(id);
	       
	}
 
	if( pear_session.state == PEAR_StateAttach)
	{
	        data = json_object_get(message, "data");
		 json_t * id = json_object_get(data, "id");
		 pear_session.handle_id = json_integer_value(id);
	}
	if( pear_session.state == PEAR_StateSDP)
	{
  
	        data = json_object_get(message, "jsep");
		 json_t * sdp = json_object_get(data, "sdp");
		 strcpy(pear_session.sdp,json_string_value(sdp));
		
		 //JANUS_LOG(LOG_INFO, "[pear]  sdp : %s...\n", pear_session.sdp);
		// pear_send_sdp_signal();
		 pear_send_sdp_signal_sample();
	}
	pear_session.state =pear_session.state +1;
	json_decref(message);
	pear_dump_session();
	return 0;
}
void janus_pear_session_over(void *transport, guint64 session_id, gboolean timeout) {
     return 0;
}
static janus_transport pear_transport =
	JANUS_TRANSPORT_INIT (
		.init = janus_pear_init,
		.destroy = janus_pear_destroy,

		.get_api_compatibility = pear_get_api_compatibility,
		.get_version = pear_get_version,
		.get_version_string = pear_get_version_string,
		.get_description = pear_get_description,
		.get_name = pear_get_name,
		.get_author = pear_get_author,
		.get_package = pear_get_package,

		.is_janus_api_enabled = pear_is_janus_api_enabled,
		.is_admin_api_enabled = pear_is_admin_api_enabled,

		.send_message = janus_pear_send_message,
		.session_created = pear_session_created,
		.session_over = janus_pear_session_over,
	);

#include "base64.h"
void pear_handle_datachannel_file_test()
{   

    int chunksize = 800;
    int chunks = 0;
    char buf[4096];
    char buf_base64[4096];
    FILE *f = fopen("pear.png", "rb");
    fseek(f, 0, SEEK_END);
    long pos = ftell(f);
    fseek(f, 0, SEEK_SET);
    chunks=pos/chunksize;
    if(pos%chunksize)
    {
        chunks = chunks +1;
    }
    JANUS_LOG(LOG_DBG, "[pear] file size is %d chunks is %d \r\n",pos,chunks);
    int i=0;
    int nread=0;

    char * start_temp  = "{\"start\":true,\"uuid\":\"1001\",\"maxChunks\":%d}";
    char * data_temp  = "{\"currentPosition\":%d,\"uuid\":\"1001\",\"maxChunks\":%d,\"value\":\"data:;base64,%s\"}";
    char * end_temp  = "{\"end\":true,\"uuid\":\"1001\",\"maxChunks\":%d}";

    sprintf(buf,start_temp,chunks);	
    JANUS_LOG(LOG_DBG,"%s\r\n",buf);
    for(i=0;i<chunks;i++)
    {
         memset(buf,0x00,4096);
         nread = fread(buf, 1, 800, f);
	  if(!nread)
	  {
	      JANUS_LOG(LOG_DBG, "no more chunks");
		break;
	  }
	  JANUS_LOG(LOG_DBG,"read bytes is %d \r\n",nread);
	  Base64encode(buf_base64,buf,nread);
	  sprintf(buf,data_temp,i,chunks,buf_base64);
	  
	  JANUS_LOG(LOG_DBG,"%s\r\n",buf);
    }
     memset(buf,0x00,4096);
     sprintf(buf,end_temp,chunks);	
    JANUS_LOG(LOG_DBG,"%s\r\n",buf);


    if (!nread) {
        JANUS_LOG(LOG_DBG, "Failed to read the config file or nothing in the config file.");
	 fclose(f);
	 return NULL;
    }
   fclose(f);
     
     
}

void pear_init_janus(void *data)
{
   //{"janus":"create","transaction":"o53t2NLXPMVb"}
  //pear_handle_datachannel_file_test();
  //return;
  JANUS_LOG(LOG_DBG, "Failed to read the config file or nothing in the config file.");

   
   pear_session.session_id=0;
   pear_session.handle_id=0;
   pear_session.state = PEAR_StateCreate;
   json_t * req= json_object();
   json_t * body= NULL;
   json_object_set_new(req, "janus", json_string("create"));
   json_object_set_new(req, "transaction", json_string("o53t2NLXP001"));
   char *payload = json_dumps(req, json_format);
   printf("[pear] send req  is \n%s\n",payload);
   
   janus_request *request = janus_request_new(&pear_transport, NULL, NULL, FALSE, req);
   //janus_process_incoming_request(&request);
   GError *tperror = NULL;
   g_thread_pool_push(tasks, request, &tperror);

  
   sleep(1);
   // {"janus":"attach","plugin":"janus.plugin.textroom","transaction":"eqjcjpCKVsBc","session_id":5840022919692368}

   req= json_object();
   json_object_set_new(req, "janus", json_string("attach"));
   json_object_set_new(req, "plugin", json_string("janus.plugin.textroom"));
   json_object_set_new(req, "transaction", json_string("o53t2NLXP002"));
   json_object_set_new(req, "session_id", json_integer(pear_session.session_id));

   payload = json_dumps(req, json_format);
   printf("[pear] send req  is \n%s\n",payload);

   request = janus_request_new(&pear_transport, NULL, NULL, FALSE, req);
   g_thread_pool_push(tasks, request, &tperror);

   sleep(1);
   //{"janus":"message","body":{"request":"setup"},"transaction":"icaQQcvLxxDn","session_id":5840022919692368,"handle_id":2262232448363641}
   req= json_object();
   json_object_set_new(req, "janus", json_string("message"));
   json_object_set_new(req, "transaction", json_string("o53t2NLXP003"));
   json_object_set_new(req, "session_id", json_integer(pear_session.session_id));
   json_object_set_new(req, "handle_id", json_integer(pear_session.handle_id));
   body = json_object();
   json_object_set_new(body, "request", json_string("setup"));
   json_object_set_new(req, "body", body);

   payload = json_dumps(req, json_format);
   printf("[pear] send req  is \n%s\n",payload);

   request = janus_request_new(&pear_transport, NULL, NULL, FALSE, req);
   g_thread_pool_push(tasks, request, &tperror);

   sleep(2);
  pear_init_signal();
   
   return;
}
#endif

void pear_send_answer_message()
{
    //{"janus":"message","body":{"request":"ack"},"transaction":"FUWWe3M11TKd",
   // "jsep":{"type":"answer","sdp":""},"session_id":5840022919692368,"handle_id":2262232448363641}
   GError *tperror = NULL;
   json_t * req= json_object();
   json_object_set_new(req, "janus", json_string("message"));
   json_object_set_new(req, "transaction", json_string("o53t2NLXP004"));
   json_object_set_new(req, "session_id", json_integer(pear_session.session_id));
   json_object_set_new(req, "handle_id", json_integer(pear_session.handle_id));
   
   json_t * body = json_object();
   json_object_set_new(body, "request", json_string("ack"));
   json_object_set_new(req, "body", body);


   json_t * jsep = json_object();
   json_object_set_new(jsep, "type", json_string("answer"));
    json_object_set_new(jsep, "sdp", json_string(pear_session.answer));
   json_object_set_new(req, "jsep", jsep);

   char * payload = json_dumps(req, json_format);
   printf("[pear] send req  is \n%s\n",payload);

    janus_request *request   = janus_request_new(&pear_transport, NULL, NULL, FALSE, req);
   g_thread_pool_push(tasks, request, &tperror);
}

// {"janus":"trickle","candidate":{"completed":true},"transaction":"Tk9ug2rnpEhI","session_id":5840022919692368,"handle_id":2262232448363641}
void pear_send_candidate_completed_message()
{
       GError *tperror = NULL;
       json_t * req= json_object();
	 json_t * candidate= json_object();
	 json_object_set_new(req, "janus", json_string("trickle"));
	 json_object_set_new(req, "session_id", json_integer(pear_session.session_id));
        json_object_set_new(req, "handle_id", json_integer(pear_session.handle_id));
	 json_object_set_new(req, "transaction", json_string("o53t2NLXP005"));

	 json_object_set_new(candidate, "completed", json_true());

	 json_object_set_new(req, "candidate", candidate);

	 char * payload = json_dumps(req, json_format);
        printf("[pear] send req  is \n%s\n",payload);

        janus_request *request   = janus_request_new(&pear_transport, NULL, NULL, FALSE, req);
        g_thread_pool_push(tasks, request, &tperror);
}
//{"janus":"trickle","candidate":{"candidate":"","sdpMid":"data","sdpMLineIndex":0},"transaction":"Qn6UqjRYkOuZ","session_id":5840022919692368,"handle_id":2262232448363641}


void pear_send_candidate_message()
{
       GError *tperror = NULL;
       json_t * req= json_object();
	 json_t * candidate= json_object();
	 json_object_set_new(req, "janus", json_string("trickle"));
	 json_object_set_new(req, "session_id", json_integer(pear_session.session_id));
        json_object_set_new(req, "handle_id", json_integer(pear_session.handle_id));
	  json_object_set_new(req, "transaction", json_string("o53t2NLXP005"));

	 json_object_set_new(candidate, "candidate", json_string(pear_session.candidate));
	 json_object_set_new(candidate, "sdpMid", json_string("data"));
	 json_object_set_new(candidate, "sdpMLineIndex", json_integer(0));
	 json_object_set_new(req, "candidate", candidate);

	 char * payload = json_dumps(req, json_format);
        printf("[pear] send req  is \n%s\n",payload);

        janus_request *request   = janus_request_new(&pear_transport, NULL, NULL, FALSE, req);
        g_thread_pool_push(tasks, request, &tperror);
}




